import java.io.*;
import java.nio.charset.StandardCharsets;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: 25397
 * Date: 2021-12-07
 * Time: 19:22
 */
public class TestDemo {
    //io流，input和output
    //输入：读取 磁盘、光盘等存储设备的外部数据 到程序（内存）
    //输出：将程序（内存）数据输出到磁盘、光盘等存储设备中
    //文件流、缓冲流（重点）

    /*public static void main(String[] args) throws IOException {
        //File能新建、删除、重命名文件和目录，但File不能访问文件内容本身
        //如果需要访问文件内容本身，需要使用输入/输出流
        File file=new File("helloWorld.txt");//相对路径
        //Public File(String pathname)
        //以pathname为路径创建File对象
        //路径又分绝对路径和相对路径
        //相对——在当前工程（文件）下
        //绝对——包括盘符在内的完整地址

        boolean b=file.exists();//判断文件是否存在
        System.out.println(b);//false

        //创建一个文件
        if(!file.exists()){
            boolean b1=file.createNewFile();
            System.out.println(b1);//创建成功返回true，不成功返回false
        }


        //删除一个文件
        System.out.println(file.delete());

        //绝对路径测试
        File file1=new File("e:\\test\\test.txt");
        b= file1.exists();
        System.out.println(b);

        //删除该文件
        file1.delete();


        //不仅可以创建文件，也可以创建文件夹
        File file2=new File("hh");
        System.out.println(file2.exists());
        if(!file2.exists()){
            file2.mkdir();//在当前文件下，创建一个名为“hh”的文件夹
        }

    }*/


    //FileInputStream:字节流、节点流、输入流
    //从一个具体的文件中读取其内容到控制台上
    // （你可以理解为在具体文件和控制台中间搭建一个管子，数据可以通过这个管子流到控制台）
    public void testFileInputStream() throws IOException {
        //1.创建一个File的对象
        File file=new File("helloWorld.txt");

        //2.将此File类的对象作为形参传递给InputStream的实现类FileInputStream的构造器中
        FileInputStream fis=null;
        try{
            fis=new FileInputStream(file);
            //3.通过调用流的的read（）方法将文件中的内容读入
            int i=0;
            while((i=fis.read())!=-1){//i会接收对应字符的Ascii码
                System.out.print((char)i);
            }
        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if(fis!=null){
                    fis.close();
                }
            }catch (IOException x){
                x.printStackTrace();
            }
        }
        fis.close();//这个需要我们手动关闭一下，比如你打开一个文件，需要关上
    }

    public void testFileOutputStream() throws FileNotFoundException {
        File file =new File("hello.txt");
        FileOutputStream fos=null;
        try{
             fos=new FileOutputStream(file);
             byte[] b="ni hao".getBytes(StandardCharsets.UTF_8);
             fos.write(b);
        }catch (FileNotFoundException f){
            f.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if(fos!=null){
                try{
                    fos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    //从源文件中读取内容，并写入到目标文件中（相当于文件的复制）
    //源文件内容会先“流”到程序，再由程序“流”到目标文件
    //流相当于一个管子
    public void testFileInputOutputStream() throws IOException {
        File src=new File("hello.txt");//源文件
        File des=new File("helloWorld.txt");//目标文件

        FileInputStream fis=null;
        FileOutputStream fos=null;

        try{
            fis=new FileInputStream(src);//src的内容流到fis(fis是src和程序之间的管子)
            fos=new FileOutputStream(des);//程序的内容流到des（fos是des和程序之间的管子）

            byte[]b=new byte[10];//一个char一个char传效率比较低，我们这里创建10个字节大小的数组来接收（1次接收10个）
            int len;
            while((len=fis.read(b))!=-1){
                fos.write(b,0,len);//从下标0开始写，写len个
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关流和脱衣服一样，我们穿的时候是先穿里面的，后穿外面的
            //脱衣服的时候，是先脱外面的，后脱里面的
            //开流是先开src和程序的（fis） 后开程序和des的（fos）
            //关流就应该先关fos再关fis
            fos.close();
            fis.close();
        }
    }

    public void copyFiles(String src, String des) throws IOException {
        File file1=new File(src);//源文件
        File file2=new File(des);//目标文件

        FileInputStream fis=null;
        FileOutputStream fos=null;

        try{
            fis=new FileInputStream(file1);//src的内容流到fis(fis是src和程序之间的管子)
            fos=new FileOutputStream(file2);//程序的内容流到des（fos是des和程序之间的管子）

            byte[]b=new byte[10];//一个char一个char传效率比较低，我们这里创建10个字节大小的数组来接收（1次接收10个）
            int len;
            while((len=fis.read(b))!=-1){
                fos.write(b,0,len);//从下标0开始写，写len个
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关流和脱衣服一样，我们穿的时候是先穿里面的，后穿外面的
            //脱衣服的时候，是先脱外面的，后脱里面的
            //开流是先开src和程序的（fis） 后开程序和des的（fos）
            //关流就应该先关fos再关fis
            fos.close();
            fis.close();
        }
    }
    public void testCopyFile() throws IOException {
        String src="测试图片.jpg";
        String des="1.jpg";
        copyFiles(src,des);
    }

    //通过FileWriter和FileReader实现文件的复制
    //FileWriter和FileReader是用来处理文本文件的（字符流）
    //InputStream和OutputStream是用来处理二进制文件的（字节流）
    //文本文件只能存储char型，二进制文件能存储各种类型
    //文本文件可以复制图片，视频等等...

    //FileWriter和FileReader与InputStream和OutputStream的区别就是类变了，然后输入输出的计量单位变了，其他的思路都是一样的
    public void copyFiles1(String src, String des) throws IOException {
        File file1=new File(src);//源文件
        File file2=new File(des);//目标文件

        FileReader fr=null;
        FileWriter fw=null;

        try{
            fr=new FileReader(file1);//src的内容流到fis(fis是src和程序之间的管子)
            fw=new FileWriter(file2);//程序的内容流到des（fos是des和程序之间的管子）

            char[]b=new char[10];//一个char一个char传效率比较低，我们这里创建10个字节大小的数组来接收（1次接收10个）
            int len;
            while((len=fr.read(b))!=-1){
                fw.write(b,0,len);//从下标0开始写，写len个
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            //关流和脱衣服一样，我们穿的时候是先穿里面的，后穿外面的
            //脱衣服的时候，是先脱外面的，后脱里面的
            //开流是先开src和程序的（fis） 后开程序和des的（fos）
            //关流就应该先关fos再关fis
            fw.close();
            fr.close();
        }
    }
    public void testCopyFile1() throws IOException {
        String src="测试图片.jpg";
        String des="2.jpg";
        copyFiles(src,des);
    }


    //缓冲流(是作用在节点流之上的,节点流就是FileInputStream和FileOutputStream)
    //输入流：BufferedInputStream、BufferedReader
    //输出流：BufferedOutputStream、BufferedWriter
    //用Buffered包装后，可以提高运行速度
    // 也就是缓冲流的作用——它是不堵塞的，你直接用reader或writer之类的会堵塞
    public  void testBufferedInputStream() throws IOException {
        File file1=new File("测试图片.jpg");
        File file2=new File("2.jpg");
        FileInputStream fis=null;
        FileOutputStream fos=null;
        BufferedInputStream bis=null;
        BufferedOutputStream bos=null;
        try{
            fis=new FileInputStream(file1);
            fos= new FileOutputStream(file2);

             bis=new BufferedInputStream(fis);
             bos=new BufferedOutputStream(fos);
        }catch (FileNotFoundException e){
            e.printStackTrace();
        }finally {
            if(bos!=null){
                bos.close();
            }
            else if(bis!=null){
                bis.close();
            }
        }

    }


    public static void main(String[] args) throws IOException {
        TestDemo testDemo=new TestDemo();
        //testDemo.testFileInputStream();
        //testDemo.testFileOutputStream();
        //testDemo.testFileInputOutputStream();
        //testDemo.testCopyFile();
        testDemo.testCopyFile1();

    }
}
